

#include "channel.h"
#include "data_buffer.h"
#include "define.h"
#include "loop_event.hpp"
#include <cerrno>
#include <sys/epoll.h>
#include <iostream>
#include <unistd.h>

Channel::Channel()
{

}

Channel::Channel(LoopEvent * loop, int sockfd, WriteAbleCallback && w_func, ReadAbleCallback && r_func, ErrorCallback && e_func)
{
    m_loop_event = loop;
    
    m_socket_fd = sockfd;

    m_write_cb = w_func;
    m_read_cb  = r_func;
    m_error_cb = e_func;
}

void Channel::AddEvent(int event_type)
{
    m_event_type = event_type;
    auto self = shared_from_this();
    m_loop_event->PushTask([self, event_type](){

        self->m_channel_id = self->m_loop_event->AddEventType(self, event_type);
    });
}

void Channel::UpdateEvent(int event_type)
{
    m_event_type = event_type;
    m_loop_event->PushTask([this, event_type](){

        m_loop_event->Update(m_channel_id, event_type);
    });
}

void Channel::RemoveEvent()
{
    auto self = shared_from_this();
    m_loop_event->PushTask([self](){

        if (self->GetSocketFd() > 0)
        {
            self->m_loop_event->Remove(self->m_channel_id, self->m_event_type);
            close(self->GetSocketFd());
            self->m_socket_fd = -1;
            self->m_loop_event->PushTask([self](){
                    
                if (self->m_error_cb)
                {
                    self->m_error_cb(self->m_channel_id, 0);
                }    
            });
        }
    });
}

void Channel::EventCallback(int event_type)
{
    // if is error
    if ((event_type & EPOLLERR || event_type & EPOLLRDHUP) && m_error_cb)
    {
        // use getopt();
        m_error_cb(m_channel_id, -1);
        return;
    }
    else if (event_type & EPOLLIN && m_read_cb)
    {
        // std::cout << "epoll in" << std::endl;
        m_read_cb(m_channel_id);
    }
    if (event_type & EPOLLOUT && m_write_cb)
    {
        // std::cout << "epoll out" << std::endl;
        m_write_cb();
    }
    // call error_callback
    // if is read
    // call read_callback
    // if is write
    // call write_callback
    // register
}

